import bge
import Rasterizer
from mathutils import Vector
import starfield
import math




class Camera:
	def __init__(self):
		#define the objects in the camera rig
		self.cam = bge.logic.getCurrentScene().objects["Camera"]
		self.camPos = self.cam.parent
		self.camAngle = self.camPos.parent
		self.focus = self.camAngle.parent

		self.pan_sensitivity = 8
		self.orbit_sensitivity = 2
		self.zoom_sensitivity = 2
		self.invertX = 0
		self.invertY = -1
		self.bounds = [-10,-10, 10, 10]
		self.pan_margin = .1
		self.zoom = 0
		
		self.zoommax = 0
		
		
		
		self.windowHeight = Rasterizer.getWindowHeight()
		self.windowWidth = Rasterizer.getWindowWidth()
		
		self.apply_zoom( starfield.STAR_MAX_DISTANCE*starfield.SCALE * -1 )

	def get_distance(self, v1, v2):
		return (v1-v2).magnitude 
		
	def distance_2D(self, p1, p2):
		x = p1[1] - p1[0]
		y = p2[1] - p2[0]
		d = math.sqrt(math.pow(x, 2) + math.pow(y,2))
		return d
		
	def place(self, location):
		self.focus.position = location
		
	def apply_zoom(self, amount):
		self.camPos.applyMovement( self.camPos.getAxisVect([0,1,0])*amount, False)
		
	def Pump(self):
		#filter through events and adjust rig
		mouse = bge.logic.mouse
		
		pos = list(mouse.position)

		mouse_events = mouse.events
		
		self.zoommax = self.distance_2D( [ self.bounds[0], self.bounds[2]], [self.bounds[1], self.bounds[3]] ) * 1.3
		#print("zoomax:-:-:", self.zoommax)
		self.zoom_mod = self.zoom/self.zoommax + self.zoom/self.zoommax 
		#print("zoomod:-:-:", self.zoom_mod)
		
		if self.zoom_mod > 1:
			self.zoom_mod = 1
		
		self.zoom = self.get_distance( self.focus.position, self.camPos.position)
		
		self.mod2 = self.zoommax / 30
		
		#zoom mode
		if mouse_events[bge.events.WHEELUPMOUSE] in [1,2,3] and self.zoom > 2:

			self.camPos.applyMovement( self.camPos.getAxisVect([0,1,0])*self.mod2*self.zoom_sensitivity* self.zoom_mod, False)
			
		if mouse_events[bge.events.WHEELDOWNMOUSE] in [1,2,3] and self.zoom < self.zoommax: 
			self.camPos.applyMovement( self.camPos.getAxisVect([0,-1,0])*self.mod2*self.zoom_sensitivity* self.zoom_mod, False)
			
		if mouse_events[bge.events.MIDDLEMOUSE] in [1]:
			self.orbit_point = pos
		if mouse_events[bge.events.MIDDLEMOUSE] in [2]:
			amount = [pos[0] - self.orbit_point[0], pos[1] - self.orbit_point[1] ]
			self.orbit_point = pos
			self.focus.applyRotation( [0 ,0,-amount[0]*self.orbit_sensitivity ], False )
			self.camAngle.applyRotation( [amount[1]*self.orbit_sensitivity * self.invertY ,0,0], True )

		else:
			#pan mode
			pos = [pos[0]-.5, pos[1]-.5]
			#need two modifiers up to 1,-1
			d= 0
			j = 0
			if  pos[0]  < -.5+self.pan_margin: #left
				d = pos[0] + ( .5-self.pan_margin) 
			if  pos[0]  > .5-self.pan_margin: #right
				d = pos[0] - ( .5-self.pan_margin) 
			
			if  pos[1]  < -.5+self.pan_margin:
				j = pos[1] + ( .5-self.pan_margin) 
			if  pos[1]  > .5-self.pan_margin:
				j = pos[1] - ( .5-self.pan_margin)

			if d < -self.pan_margin:
				d = - self.pan_margin
			if d > self.pan_margin:
				d = self.pan_margin
			if j < -self.pan_margin:
				j = - self.pan_margin
			if j > self.pan_margin:
				j = self.pan_margin
			
			fpos = self.focus.position
			ps = self.pan_sensitivity * self.zoom_mod
			npos = [fpos[0],fpos[1]]
			
			l = list(self.focus.position)
			if l[0] < self.bounds[0]:
				l[0] = self.bounds[0]
			if l[0] > self.bounds[2]:
				l[0] = self.bounds[2]
				
			if l[1] < self.bounds[1]:
				l[1] = self.bounds[1]
			if l[1] > self.bounds[3]:
				l[1] = self.bounds[3]
			self.focus.position = l
			
			self.focus.applyMovement( [d*ps, -j*ps, 0], True )
		
	
def main():
	cont = bge.logic.getCurrentController()
	own = cont.owner
	if 'init' not in own:
		own['init'] = 1
		# Create our system and show the mouse
		starfield.camera = Camera()
	else:
		starfield.camera.Pump()
main()